home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / cagd_lib / cagdsrev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-31  |  7.7 KB  |  215 lines

  1. /******************************************************************************
  2. * CagdSRev.c - Surface of revolution out of a given profile.              *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Mar. 91.                          *
  5. ******************************************************************************/
  6.  
  7. #include "cagd_loc.h"
  8.  
  9. static int 
  10.     CircRationalKnotVector[12] = { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 },
  11.     CircPolynomialKnotVector[17] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
  12.                             3, 3, 3, 4, 4, 4, 4 };
  13.  
  14. static CagdRType
  15.     PolyApproxRotAngles[] = {
  16.     0,
  17.     33.523898, /* arcsin(4 (sqrt(2) - 1) / 3) */
  18.     90 - 33.523898,
  19.     90
  20.     };
  21.  
  22. /*****************************************************************************
  23. * DESCRIPTION:                                                               M
  24. * Constructs a surface of revolution around the Z axis of the given profile  M
  25. * curve. Resulting surface will be a Bspline surface, while input may be     M
  26. * either a Bspline or a Bezier curve.                                        M
  27. *                                                                            *
  28. * PARAMETERS:                                                                M
  29. *   Crv:        To create surface of revolution around Z with.               M
  30. *                                                                            *
  31. * RETURN VALUE:                                                              M
  32. *   CagdSrfStruct *:  Surface of revolution.                                 M
  33. *                                                                            *
  34. * KEYWORDS:                                                                  M
  35. *   CagdSurfaceRev, surface of revolution, surface constructors              M
  36. *****************************************************************************/
  37. CagdSrfStruct *CagdSurfaceRev(CagdCrvStruct *Crv)
  38. {
  39.     int i, j, i9,
  40.     Len = Crv -> Length;
  41.     CagdPointType
  42.     PType = Crv -> PType;
  43.     CagdRType **SrfPoints,
  44.     sin45 = sin(M_PI / 4.0),
  45.     **CrvPoints = Crv -> Points;
  46.     CagdSrfStruct
  47.     *Srf = BspPeriodicSrfNew(9, Len, 3, Crv -> Order,
  48.                  FALSE, Crv -> Periodic, CAGD_PT_P3_TYPE);
  49.  
  50.     for (i = 0; i < 12; i++)
  51.     Srf -> UKnotVector[i] = (CagdRType) CircRationalKnotVector[i];
  52.  
  53.     switch (Crv -> GType) {
  54.     case CAGD_CBEZIER_TYPE:
  55.         BspKnotUniformOpen(Len, Crv -> Order, Srf -> VKnotVector);
  56.         break;
  57.     case CAGD_CBSPLINE_TYPE:
  58.         CAGD_GEN_COPY(Srf -> VKnotVector, Crv -> KnotVector,
  59.               sizeof(CagdRType) * (CAGD_CRV_PT_LST_LEN(Crv) +
  60.                                            Crv -> Order));
  61.         break;
  62.     case CAGD_CPOWER_TYPE:
  63.         CAGD_FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  64.         return NULL;
  65.     default:
  66.         CAGD_FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  67.         return NULL;
  68.     }
  69.  
  70.     SrfPoints = Srf -> Points;
  71.  
  72.     /* For each control point in the original curve - generate 9 points that */
  73.     /* Form a circle perpendicular to the Z axis.                 */
  74.     for (i = i9 = 0; i < Len; i++, i9 += 9) {
  75.     SrfPoints[W][i9] = 1.0;
  76.     switch (PType) {
  77.         case CAGD_PT_P3_TYPE:
  78.         SrfPoints[W][i9] = CrvPoints[W][i];
  79.         case CAGD_PT_E3_TYPE:
  80.         SrfPoints[X][i9] = CrvPoints[X][i];
  81.         SrfPoints[Y][i9] = CrvPoints[Y][i];
  82.         SrfPoints[Z][i9] = CrvPoints[Z][i];
  83.         break;
  84.         default:
  85.         CAGD_FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
  86.         break;
  87.     }
  88.  
  89.     /* Last point is exactly the same as first one in circle - copy it.  */
  90.     for (j = W; j <= Z; j++)
  91.         SrfPoints[j][i9 + 8] = SrfPoints[j][i9];
  92.  
  93.     /* The Z components are identical in all circle, while the XY        */
  94.     /* components are rotated 45 degrees at a time:                 */
  95.     for (j = 1; j < 8; j++) {
  96.         SrfPoints[W][i9 + j] = SrfPoints[W][i9];
  97.         SrfPoints[X][i9 + j] = SrfPoints[X][i9 + j - 1] * sin45 -
  98.                    SrfPoints[Y][i9 + j - 1] * sin45;
  99.         SrfPoints[Y][i9 + j] = SrfPoints[X][i9 + j - 1] * sin45 +
  100.                    SrfPoints[Y][i9 + j - 1] * sin45;
  101.         SrfPoints[Z][i9 + j] = SrfPoints[Z][i9];
  102.     }
  103.  
  104.     /* And finally we need to compensate for the W's on every second pt. */
  105.     for (j = 1; j < 8; j += 2) {
  106.         SrfPoints[W][i9 + j] *= sin45;
  107.         SrfPoints[Z][i9 + j] *= sin45;
  108.     }
  109.     }
  110.  
  111.     return Srf;
  112. }
  113.  
  114. /*****************************************************************************
  115. * DESCRIPTION:                                                               M
  116. * Constructs a surface of revolution around the Z axis of the given profile  M
  117. * curve. Resulting surface will be a Bspline surface, while input may be     M
  118. * either a Bspline or a Bezier curve.                                        M
  119. *   Resulting surface will be a polynomial Bspline surface, approximating a  M
  120. * surface of revolution using a polynomial circle approx.                    M
  121. * (See Faux & Pratt "Computational Geometry for Design and Manufacturing").  M
  122. *                                                                            *
  123. * PARAMETERS:                                                                M
  124. *   Crv:        To approximate a surface of revolution around Z with.        M
  125. *                                                                            *
  126. * RETURN VALUE:                                                              M
  127. *   CagdSrfStruct *:  Surface of revolution approximation.                   M
  128. *                                                                            *
  129. * KEYWORDS:                                                                  M
  130. *   CagdSurfaceRevPolynomialApprox, surface of revolution, surface           M
  131. *   constructors                                     M
  132. *****************************************************************************/
  133. CagdSrfStruct *CagdSurfaceRevPolynomialApprox(CagdCrvStruct *Crv)
  134. {
  135.     int i, j, i13,
  136.     Len = Crv -> Length;
  137.     CagdPointType
  138.     PType = Crv -> PType;
  139.     CagdRType **SrfPoints,
  140.     **CrvPoints = Crv -> Points;
  141.     CagdSrfStruct
  142.     *Srf = BspPeriodicSrfNew(13, Len, 4, Crv -> Order,
  143.                  FALSE, Crv -> Periodic, CAGD_PT_E3_TYPE);
  144.  
  145.     if (CAGD_IS_RATIONAL_CRV(Crv)) {
  146.     CAGD_FATAL_ERROR(CAGD_ERR_POLYNOMIAL_EXPECTED);
  147.     return NULL;
  148.     }
  149.  
  150.     for (i = 0; i < 17; i++)
  151.     Srf -> UKnotVector[i] = (CagdRType) CircPolynomialKnotVector[i];
  152.  
  153.     switch (Crv -> GType) {
  154.     case CAGD_CBEZIER_TYPE:
  155.         BspKnotUniformOpen(Len, Crv -> Order, Srf -> VKnotVector);
  156.         break;
  157.     case CAGD_CBSPLINE_TYPE:
  158.         CAGD_GEN_COPY(Srf -> VKnotVector, Crv -> KnotVector,
  159.               sizeof(CagdRType) * (CAGD_CRV_PT_LST_LEN(Crv) +
  160.                                 Crv -> Order));
  161.         break;
  162.     case CAGD_CPOWER_TYPE:
  163.         CAGD_FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  164.         return NULL;
  165.     default:
  166.         CAGD_FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  167.         return NULL;
  168.     }
  169.  
  170.     SrfPoints = Srf -> Points;
  171.  
  172.     /* For each control point in original curve - generate 13 points that    */
  173.     /* Form a circle 9approximation) perpendicular to the Z axis.         */
  174.     for (i = i13 = 0; i < Len; i++, i13 += 13) {
  175.     int Quad;
  176.  
  177.     switch (PType) {
  178.         case CAGD_PT_E3_TYPE:
  179.         SrfPoints[X][i13] = CrvPoints[X][i];
  180.         SrfPoints[Y][i13] = CrvPoints[Y][i];
  181.         SrfPoints[Z][i13] = CrvPoints[Z][i];
  182.         break;
  183.         default:
  184.         CAGD_FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
  185.         break;
  186.     }
  187.  
  188.     /* Last point is exactly the same as first one in circle - copy it.  */
  189.     for (j = X; j <= Z; j++)
  190.         SrfPoints[j][i13 + 12] = SrfPoints[j][i13];
  191.  
  192.     /* The Z components are identical in all circle, while the XY        */
  193.     /* components are functions of PolyApproxRotAngles:             */
  194.     for (Quad = 0, j = 1; j < 12; j++) {
  195.         CagdRType Angle, CosAngle, SinAngle;
  196.  
  197.         if (j % 3 == 0)
  198.         Quad++;
  199.         Angle = Quad * 90 + PolyApproxRotAngles[j % 3];
  200.         CosAngle = cos(DEG2RAD(Angle));
  201.         SinAngle = sin(DEG2RAD(Angle));
  202.  
  203.         if (ABS(CosAngle) > ABS(SinAngle))
  204.         CosAngle /= ABS(CosAngle);
  205.         else
  206.         SinAngle /= ABS(SinAngle);
  207.         SrfPoints[X][i13 + j] = SrfPoints[X][i13] * CosAngle;
  208.         SrfPoints[Y][i13 + j] = SrfPoints[X][i13] * SinAngle;
  209.         SrfPoints[Z][i13 + j] = SrfPoints[Z][i13];
  210.     }
  211.     }
  212.  
  213.     return Srf;
  214. }
  215.